/*********************************************************************
 * Software License Agreement
 *
 * Copyright (C) 2010 Cross The Road Electronics.  All rights
 * reserved.
 *
 * Cross The Road Electronics (CTRE) licenses to you the right to 
 * use, copy, modify, merge, publish, distribute, sublicense, and/or 
 * sell copies of the Software ONLY when in use with CTRE's 2CAN 
 * Ethernet CAN Gateway.
 *
 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, 
 * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
 *
********************************************************************/
#ifndef _2CANClient__h_
#define _2CANClient__h_

#include "../Common/2CANClientDefs.h"
#include "../Common/2CAN_DLL_API.h"
#include "../Common/Os Abstraction/stdint.h"
#include "../Common/NetComm/2CAN_DataObjects.h"
#include "../Common/NetComm/UDPClient.h"
#include "../Common/Os Abstraction/OS_Task.h"
#include "../Common/Os Abstraction/OS_Event.h"
#include "../Common/Os Abstraction/OS_Semaphore.h"

class C2CANClient
{
	public:
		C2CANClient();
		~C2CANClient();

		//********************************* 2CAN Base API *********************************//
		static ctr_error_t Find2Can(Found2Can * found2can,uint32_t options);
		ctr_error_t Init(const char * ip);
		ctr_error_t SetCommPeriod(uint32_t iPeriod);
		ctr_error_t Stop();
		ctr_error_t SetActiveRcmNodeid(uint16_t nodeId);
		ctr_error_t Enable(EnableState enableState,uint64_t outputEnableBits);
		ctr_error_t IsEnabled(uint32_t *is_enabled);

		//********************************* Node Base API *********************************//
		ctr_error_t SetPWM(ctr_nodeType_t node,int param,int channel, int16_t pulseWidth);
		ctr_error_t GetADC(ctr_nodeType_t node,int param,int channel,uint32_t * result);
		ctr_error_t GetPosition(ctr_nodeType_t node,int param,int channel,uint32_t * result);
		ctr_error_t GetVelocity(ctr_nodeType_t node,int param,int channel,uint32_t * result);
		ctr_error_t SetSolenoid(ctr_nodeType_t node,int param,int channel, bool enable); 
		ctr_error_t SetRelay(ctr_nodeType_t node,int param,int channel, unsigned char state);
		ctr_error_t GetGPIO(ctr_nodeType_t node,int param,uint32_t * result);
		//********************************* Raw CAN API *********************************//
		ctr_error_t SetFilter(	unsigned int iFilterIdx,
						const CANFrame_t * pMsgData,
						const CANFrame_t * pMsgMask);

		ctr_error_t ClearFilter(unsigned int iFilterIdx);

		ctr_error_t GetFrames(	CANFrame_t * frames,
							uint32_t capacity,
							uint32_t * num_msgs);

		ctr_error_t SendFrames(	const CANFrame_t * frames,
								uint32_t num_msgs);

		ctr_error_t GetCommStats(CommStats * stats);

	private:
		C2CANClient(const C2CANClient & rhs) : 
			g_StopEvent(L"StopApp",true),
			g_HasStoppedEvent(L"HasStopped",true),
			g_AckReceived(L"AckReceived",true)
		   {}

		void SendRCMOut();;
		void SendJagOut();
		void SendEnableOut();
		void SendFrameOut(const STo2CAN_CANFrame & canframe);
		bool SendFilterUpdate(	unsigned int iFilterIdx,
								STo2CAN_CANFrame & value,
								STo2CAN_CANFrame & mask);

		int ProcessRxData(CUDPClient & client,const uint8_t * pData, uint32_t ulNumBytes);
		int EmptyReceiveData(CUDPClient & client);
		void ProcessUDP();
		void Process10Ms();
		static unsigned int bt2CAN_RC_StaticThread(void * lpParam);
		unsigned int bt2CAN_RC_Thread();
		void InitVars();
		void ClearInputData();
		
		char g_IP[100];
		unsigned long g_iPeriod;
		OS_Task * g_task;
		OS_Event g_StopEvent;
		OS_Event g_HasStoppedEvent;
		OS_Event g_AckReceived;

		STo2CAN_HeartBeat hb_in;

		OS_Semaphore g_sem;
		STo2CAN_RCMPacket rcm_out;
		SFrom2CAN_RCMPacket rcm_in;
		STo2CAN_UpdateJagPacket jag_out;
		STo2CAN_EnablePacket enable_out;
		CommStats _commStates;

		CUDPClient udp_client;
		CUDPClient udp_hb;

		EnableState _enabledState;
		bool bEnabled;
		bool bSendHB;
		signed long heart_beat_timeout;

		static const uint32_t inFramesCap = 100;
		CANFrame_t inFrames[inFramesCap];
		uint32_t inFramesCnt;
		uint32_t inFramesIn;
		uint32_t inFramesOut;
};

typedef C2CANClient * P2CANClient;

#endif // _2CANClient__h_











